/*
This file is part of buco.  
Copyright (c) 2012 Christopher Pawelzik <christopher@cpawelzik.com>

Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php 
*/ 
package buco.integrity.classes;

import java.util.BitSet;
import java.util.List;

import buco.core.api.*;

public class ClassIntegrityCheck extends IntegrityCheck {
	
	@Override
	public void checkIntegrity(Bundle bundle, IntegrityReport report) {
		// Get the required classes for this bundle 
		List<RequireClass> requireClassConstraints = bundle.getSemanticConstraints("requireClass", RequireClass.class);
		if(requireClassConstraints.size() == 0)
			return;
		// To mark which requirements are satisfied 
		BitSet satisfied = new BitSet(requireClassConstraints.size()); 
		// Get the active wires that go out from this bundle
		List<BundleWire> wires = composition.getOutgoingWires(bundle, true); 		
		
		for(BundleWire wire : wires) { 
			Bundle candidate = wire.getTo();
			
			for(int i=0; i < requireClassConstraints.size(); i++) { 
				if(hasClass(candidate, requireClassConstraints.get(i))) {
					satisfied.set(i);
				}
			}
		}		
		
		// Output warnings
		for(int i=0; i < requireClassConstraints.size(); i++) { 
			if(!satisfied.get(i)) { 
				report.warn(String.format("Required class '%s' was not found." ,
						requireClassConstraints.get(i).getName()));
			}
		}
	}
	
	private boolean hasClass(Bundle candidat, RequireClass clazz) { 
		List<HasClass> hasClassConstraints = candidat.getSemanticConstraints("hasClass", HasClass.class);		
		for(int i=0; i < hasClassConstraints.size(); i++) { 
			if(hasClassConstraints.get(i).satisfies(clazz)) {
				return true;
			}
		}
		
		return false;
	}

}
